home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_200
/
204_01
/
register.c
< prev
next >
Wrap
Text File
|
1980-01-01
|
5KB
|
162 lines
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "gen.h"
#include "cglbdec.h"
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
/*
* this module handles the allocation and de-allocation of
* temporary registers. when a temporary register is allocated
* the stack depth is saved in the field deep of the address
* mode structure. when validate is called on an address mode
* structure the stack is popped until the register is restored
* to it's pre-push value.
*/
struct amode push[] = { {am_adec,7} },
pop[] = { {am_ainc,7} };
int next_data,
next_addr;
int max_data,
max_addr;
gen_push(reg,rmode)
/*
* this routine generates code to push a register onto the stack
*/
int reg, rmode;
{ struct amode *ap1;
ap1 = xalloc(sizeof(struct amode));
ap1->preg = reg;
ap1->mode = rmode;
gen_code(op_move,4,ap1,push);
}
gen_pop(reg,rmode)
/*
* generate code to pop the primary register in ap from the
* stack.
*/
int reg, rmode;
{ struct amode *ap1;
ap1 = xalloc(sizeof(struct amode));
ap1->preg = reg;
ap1->mode = rmode;
gen_code(op_move,4,pop,ap1);
}
initstack()
/*
* this routine should be called before each expression is
* evaluated to make sure the stack is balanced and all of
* the registers are marked free.
*/
{ next_data = 0;
next_addr = 0;
max_data = 2;
max_addr = 1;
}
validate(ap)
/*
* validate will make sure that if a register within an address
* mode has been pushed onto the stack that it is popped back
* at this time.
*/
struct amode *ap;
{ switch( ap->mode )
{
case am_direct:
case am_immed:
return; /* no registers used */
case am_dreg:
if( ap->preg > 2 )
return; /* not a temporary */
if( max_data - ap->deep >= 3 )
{
gen_pop(ap->preg,am_dreg);
--max_data;
}
break;
default:
if( ap->preg > 1 )
return; /* not a temp register */
if( max_addr - ap->deep >= 2 )
{
gen_pop(ap->preg,am_areg);
--max_addr;
}
break;
}
}
struct amode *temp_data()
/*
* allocate a temporary data register and return it's
* addressing mode.
*/
{ struct amode *ap;
ap = xalloc(sizeof(struct amode));
ap->mode = am_dreg;
ap->preg = next_data % 3;
ap->deep = next_data;
if( next_data > max_data )
{
gen_push(next_data % 3,am_dreg);
max_data = next_data;
}
++next_data;
return ap;
}
struct amode *temp_addr()
/*
* allocate a temporary address register and return it's
* addressing mode.
*/
{ struct amode *ap;
ap = xalloc(sizeof(struct amode));
ap->mode = am_areg;
ap->preg = next_addr % 2;
ap->deep = next_addr;
if( next_addr > max_addr )
{
gen_push(next_addr % 2,am_areg);
max_addr = next_addr;
}
++next_addr;
return ap;
}
freeop(ap)
/*
* release any temporary registers used in an addressing mode.
*/
struct amode *ap;
{ if( ap->mode == am_immed || ap->mode == am_direct )
return; /* no registers used */
if( ap->mode == am_dreg && ap->preg < 3 )
--next_data;
else if( ap->preg < 2 )
--next_addr;
}